package cz.acies.genea.data.process;

import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

import cz.acies.genea.data.dao.GedFamilyDAO;
import cz.acies.genea.data.dao.GedPersonDAO;
import cz.acies.genea.data.persist.GedFamily;
import cz.acies.genea.data.persist.GedPerson;

public class PersonProcessor extends DefaultModulProcessor
{
	public PersonProcessor() {
		this.type = "json";
	}

	@Override
	public String executeCommand(Map<String, Object> params) {
		String result = null;
		String method = (String) params.get("processId");
		//System.out.println("method: " + method);
		if (method.equals("init")) {
		} else if (method.equals("reload")) {
		} else if (method.equals("loadRecords")) {
			result = "" + doLoadRecords(params);
		} else if (method.equals("loadDetail")) {
			result = "" + doLoadDetail(params);		
		} else if (method.equals("reloadDetail")) {
			result = "" + reloadDetail(params);
		} else if (method.equals("reloadPartners")) {
			result = "" + reloadPartners(params);
		} else if (method.equals("reloadChildren")) {
			result = "" + reloadChildren(params);
		} else if (method.equals("reloadModul")) {
			
		}
		return result;
	}

	public String doUpdate(Map<String, Object> params) {
		String result = "";
		GedPersonDAO dao = new GedPersonDAO();
		try {
			String id = (String) params.get("id");
			GedPerson record = new GedPerson(id);
			BeanUtils.populate(record, params);
			dao.update(params);
		} catch (Exception exc) {
			exc.printStackTrace();
		}
		return result;
	}
	
	public JsonElement doLoadDetail(Map<String, Object> params) {
		JsonElement result = null;
		try {
			JsonSerializer<Timestamp> ser = new JsonSerializer<Timestamp>() {
				//@Override
				public JsonElement serialize(Timestamp src, Type typeOfSrc, JsonSerializationContext context) {
					SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 
					return src == null ? null : new JsonPrimitive(StringUtils.left(sdf.format(src), 10));
				}
			};
			Gson gson = new GsonBuilder()
				.registerTypeAdapter(Timestamp.class, ser)
				.create();
			
			String id = (String) params.get("personId");
			if (id == null) {
				id = "PS-GE-000000001";
			}
			GedPersonDAO dao = new GedPersonDAO();
			GedPerson person = dao.selectById("" + id); 

			LinkedHashMap<String, Object> row = new LinkedHashMap<String, Object>();
			row.put("id", person.getId());				
			row.put("firstName", person.getFirstName());
			row.put("lastName", person.getLastName());
			row.put("maidenName", person.getMaidenName());
			row.put("gender", person.getGender());
			row.put("birthDate", DateFormatUtils.format(person.getBirthDate(), "yyyy-MM-dd"));
			row.put("birthPlace", person.getBirthPlace());
			row.put("deathDate", DateFormatUtils.format(person.getDeathDate(), "yyyy-MM-dd"));
			row.put("deathPlace", person.getDeathPlace());
//$			row.put("fatherId", person.getFatherId());
//$			row.put("fatherName", person.getFatherName());
//$			row.put("matherId", person.getMatherId());
//$			row.put("matherName", person.getMatherName());
			row.put("descript", person.getDescript());
			row.put("bookCode", person.getBookCode());
			
			result = gson.toJsonTree(person);
		} catch (Exception exc) {
			exc.printStackTrace();
		}
		return result;
	}

	public JsonElement doLoadRecords(Map<String, Object> params) {
		JsonElement result = null;
		try {
			//Gson gson = new Gson();
			JsonSerializer<Timestamp> ser = new JsonSerializer<Timestamp>() {
				//@Override
				public JsonElement serialize(Timestamp src, Type typeOfSrc, JsonSerializationContext context) {
					SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 
					return src == null ? null : new JsonPrimitive(StringUtils.left(sdf.format(src), 10));
				}
			};
			/*
			JsonDeserializer<Timestamp> deser = new JsonDeserializer<Timestamp>() {
				@Override
				public Timestamp deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
					return json == null ? null : new Timestamp(json.getAsLong());
				}
			};
			*/
			Gson gson = new GsonBuilder()
				.registerTypeAdapter(Timestamp.class, ser)
				//.registerTypeAdapter(Timestamp.class, deser)
				.create();
			
			List<Map<String, Object>> records = new ArrayList<Map<String, Object>>();
			GedPersonDAO dao = new GedPersonDAO();
			List<GedPerson> list = dao.selectAll();
			
			for (GedPerson person : list) {
				LinkedHashMap<String, Object> row = new LinkedHashMap<String, Object>();
				row.put("id", person.getId());				
				row.put("firstName", person.getFirstName());
				row.put("lastName", person.getLastName());
				row.put("maidenName", person.getMaidenName());
				row.put("gender", person.getGender());
				row.put("birthDate", DateFormatUtils.format(person.getBirthDate(), "yyyy-MM-dd"));
				row.put("birthPlace", person.getBirthPlace());
				row.put("deathDate", DateFormatUtils.format(person.getDeathDate(), "yyyy-MM-dd"));
				row.put("deathPlace", person.getDeathPlace());
//$				row.put("fatherId", person.getFatherId());
//$				row.put("fatherName", person.getFatherName());
//$				row.put("matherId", person.getMatherId());
//$				row.put("matherName", person.getMatherName());
				row.put("descript", person.getDescript());
				row.put("bookCode", person.getBookCode());

				records.add(row);
			}
			result = gson.toJsonTree(records);
		} catch (Exception exc) {
			exc.printStackTrace();
		}
		return result;
	}
	
	public synchronized String reloadDetail(Map<String, Object> params) {
		try {
			String sourceId = (String) params.get("sourceId");
			String recordId = (String) params.get("recordId");
			// System.out.println("recordId: "+recordId);
			GedPersonDAO dao = new GedPersonDAO();
			GedPerson record = dao.selectById(recordId);

			String gender = "";
			GedPerson person = new GedPerson();
			if (sourceId.equals("personPanel")) {
				person = record;
				gender = "m";
			} else if (sourceId.equals("fatherPanel")) {
				if (record != null) {
					GedFamily family = new GedFamilyDAO().selectById(record.getParents().getId());
					if (family != null) {
						GedPerson father = family.getMan();
						if (father != null) {
							person = dao.selectById(father.getId());
						}
					}
				}
				gender = "m";
			} else if (sourceId.equals("motherPanel")) {
				if (record != null) {
					GedFamily family = new GedFamilyDAO().selectById(record.getParents().getId());
					if (family != null) {
						GedPerson mother = family.getWoman();
						if (mother != null) {
							person = dao.selectById(mother.getId());
						}
					}
				}
				gender = "f";
			}
			String firstName = "";
			String lastName = "";
			String maidenName = "";

			String birthDate = "";
			String birthPlace = "";
			String deathDate = "";
			String deathPlace = "";

			if (person != null) {
				if (sourceId.equals("personPanel")) {
					gender = (person.hasGender() && person.getGender().toLowerCase().equals("f")) ? "f" : "m";
				}
			    firstName = (person.hasFirstName()) ? person.getFirstName() : "";
			    lastName = (person.hasLastName()) ? person.getLastName() : "";
			    maidenName = (person.hasMaidenName()) ? person.getMaidenName() : "";
			    
			    Date now = new Date();
			    
		        if (person.getBirthDate() instanceof Date && person.getBirthDate().compareTo(now) < 0) {
		            birthDate = "" + DateFormatUtils.format(person.getBirthDate(), "dd.MM.yyyy");
		            birthPlace = "&nbsp;("+person.getBirthPlace()+")";
		        }
		        if (person.getDeathDate() instanceof Date && person.getDeathDate().compareTo(now) < 0) {
		            deathDate = "" + DateFormatUtils.format(person.getDeathDate(), "dd.MM.yyyy");
		            deathPlace = "&nbsp;("+person.getDeathPlace()+")";
		        }
			}
			String html = 
			"<table>"+
			    "<tr>"+ 
			        "<td>"+
			            "<img style=\"width: 64px; height: 64px; margin-right: 10px;\" alt=\"\" "+ 
			               "src=\"/genea/res/icons/empty_photo_"+gender+".PNG\">"+
			        "</td>"+
			        "<td>"+
			            "<table>"+
			                "<tr style=\"padding: 2px;\">"+
			                    "<td width=\"100px\"><label>Jméno</label></td>"+
			                    "<td id=\"firstName\"><label>"+firstName+"</label></td>"+
			                "</tr>"+
			                "<tr>"+
			                    "<td><label>Příjmení</label></td>"+
			                    "<td id=\"lastName\"><label>"+lastName+"</label></td>"+
			                "</tr>"+
			                "<tr>"+
			                    "<td><label>Rodné příjmení</label></td>"+
			                    "<td id=\"maidenName\"><label>"+maidenName+"</label></td>"+
			                "</tr>"+
			                "<tr>"+
			                    "<td><label>Datum narození</label></td>"+
			                    "<td id=\"birthDate\"><label>"+birthDate+"</label></td>"+
			                    "<td id=\"birthPlace\"><label>"+birthPlace+"</label></td>"+
			                "</tr>"+
			                "<tr>"+
			                    "<td><label>Datum úmrtí</label></td>"+
		                        "<td id=\"birthDate\"><label>"+deathDate+"</label></td>"+
		                        "<td id=\"birthPlace\"><label>"+deathPlace+"</label></td>"+
			                "</tr>"+
			            "</table>"+
			        "</td>"+
			    "</tr>"+
			"</table>";
			
			response().getWriter().println(html);

		} catch (Exception exc) {
			exc.printStackTrace();
		}
		return "";
	}

	public synchronized String reloadPartners(Map<String, Object> params) {
		String data = "";
		try {
			String recordId = (String) params.get("recordId");
			GedPersonDAO dao = new GedPersonDAO();
			GedPerson record = dao.selectById(recordId);
			
			List<GedPerson> children = dao.selectPartners(record);
			List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
			for (GedPerson person : children) {
				Map<String, Object> map = new LinkedHashMap<String, Object>();
				map.put("id", person.getId());
				map.put("displayName", person.getDisplayName());
				map.put("birthday", DateFormatUtils.format(person.getBirthDate(), "d.M.yyyy"));
				list.add(map);
			}
			Gson gson = new Gson();
			data = gson.toJson(list);
			response().getWriter().println(data);
		} catch (Exception exc) {
			exc.printStackTrace();
		}
		return data;
	}

	public synchronized String reloadChildren(Map<String, Object> params) {
		String data = "";
		try {
			String recordId = (String) params.get("recordId");
			GedPersonDAO dao = new GedPersonDAO();
			GedPerson record = dao.selectById(recordId);
			List<GedPerson> children = dao.selectChildernById(record);
			
			List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
			for (GedPerson person : children) {
				Map<String, Object> map = new LinkedHashMap<String, Object>();
				map.put("id", person.getId());
				map.put("displayName", person.getDisplayName());
				map.put("birthday", DateFormatUtils.format(person.getBirthDate(), "d.M.yyyy"));
				list.add(map);
			}
			Gson gson = new Gson();
			data = gson.toJson(list);
			//System.out.println("PersonProcessor.reloadChildren().data:"+data);
			response().getWriter().println(data);
		} catch (Exception exc) {
			exc.printStackTrace();
		}
		return data;
	}
	
}
